using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

namespace Jerry.UiFrame
{
    public class JText : Text, IComponent
    {
        [SerializeField] [Tooltip("打字机效果")] private bool typewriter;

        [SerializeField] [Tooltip("打字机效果延迟时间")]
        private float delayTime;

        private string _fullText;
        private List<TagInfo> _activeTags = new List<TagInfo>();
        private bool _bTyping;
        private IComponent _componentImplementation;

        public override string text
        {
            set
            {
                base.text = value;
                if (typewriter && gameObject.activeSelf)
                {
                    _fullText = value;
                    ParseTags();
                    StartCoroutine(TypeText());
                }
            }
            get => base.text;
        }
        
        #region 打字机效果

        private void ParseTags()
        {
            _activeTags.Clear();
            bool inTag = false;
            string currentTag = "";
            int tagStartIndex = 0;

            for (int i = 0; i < _fullText.Length; i++)
            {
                if (_fullText[i] == '<')
                {
                    inTag = true;
                    tagStartIndex = i;
                    currentTag = "";
                }
                else if (_fullText[i] == '>')
                {
                    inTag = false;
                    _activeTags.Add(new TagInfo
                    {
                        StartIndex = tagStartIndex,
                        Tag = currentTag,
                        BClosing = currentTag.StartsWith("/")
                    });
                }
                else if (inTag)
                {
                    currentTag += _fullText[i];
                }
            }
        }

        private IEnumerator TypeText()
        {
            _bTyping = true;
            Stack<string> openTags = new Stack<string>();
            int currentIndex = 0;
            base.text = "";

            while (currentIndex < _fullText.Length)
            {
                if (_fullText[currentIndex] == '<')
                {
                    // 处理标签
                    var tag = _activeTags.Find(t => t.StartIndex == currentIndex);
                    if (tag != null)
                    {
                        if (tag.BClosing)
                        {
                            if (openTags.Count > 0)
                                openTags.Pop();
                        }
                        else
                        {
                            openTags.Push(tag.Tag);
                        }

                        currentIndex = tag.StartIndex + tag.Tag.Length + 2; // < + tag + >
                    }
                }
                else
                {
                    string visibleText = _fullText.Substring(0, currentIndex + 1);
                    foreach (string tag in openTags)
                    {
                        if (tag.StartsWith("color="))
                        {
                            visibleText += $"</color>";
                        }
                        else if (tag.StartsWith("size="))
                        {
                            visibleText += $"</size>";
                        }
                        else
                        {
                            visibleText += $"</{tag}>";
                        }
                    }

                    base.text = visibleText;
                    currentIndex++;
                    yield return new WaitForSeconds(delayTime);
                }
            }

            _bTyping = false;
            StopAllCoroutines();
        }

        private void Update()
        {
            if (_bTyping && Input.GetMouseButtonDown(0))
            {
                StopAllCoroutines();
                base.text = _fullText;
                _bTyping = false;
            }
        }

        #endregion

        public void SetVisible(bool bVisible)
        {
            gameObject.SetActive(bVisible);
        }

        public T GetChild<T>(string childName) where T : IComponent
        {
            var comp = transform.Find(childName).GetComponent<IComponent>();
            return (T)comp;
        }

        private class TagInfo
        {
            public int StartIndex;
            public string Tag;
            public bool BClosing;
        }
    }
}